#ifndef __DEBUG__H__
#define __DEBUG__H__
#include "sys.h"

#define DEBUG_PRINT
//#define LOG_FILE

#define INFO_LEVEL  1 
#define WARN_LEVEL  2
#define ERR_LEVEL 3


extern int debug_level;

static inline void set_debug_level(int level){
		debug_level = level;
}
static inline int get_debug_level(){
		return debug_level;
}

extern void log_init(char* filename);
extern void  log_to_file(char* str, int size);



#define BUG_ON() assert(0)

#ifdef DEBUG_PRINT
 	#define get_info(fmt, msg...)		({		\
		char buf[1024];						\
		do{									\
				int size=0;					\
				int off =0;					\
				time_t timep; 					\
				struct timeval tv;				\
				struct timezone tz;				\
				pthread_t   tid;					\
				char* st =  NULL; 				\
				gettimeofday (&tv , &tz);	\
				time(&timep); 				\
				st = ctime(&timep);			\
				st = strtok(st, "\n");		\
				tid = pthread_self();				\
				off = snprintf(buf+off,4096, "[%s:%d:%d][tid:%u][%s:%d:%s]\t",  \
					st,tv.tv_sec,tv.tv_usec,tid, __FILE__,__LINE__,__FUNCTION__);  \
				size +=off;					\
      	    			off = snprintf(buf+off,4096-size, fmt,##msg);       \
				size +=off;							\
				buf[size]='\0';					\
		}while(0);				\
		  buf;					\
 		})

		
	#define debug(level, fmt, msg...)  \
		do{                    \
	    		if (level>= debug_level) {  \
				char* str;		\
				str = get_info(fmt, ##msg);  \
      	    			printf("%s",str);       \
    			}\
		}while(0)   

		#define log_file(level, fmt, msg...)  \
		do{                    \
	    		if (level>= debug_level) {  \
				char* str;						\
				int size;					\
				str = get_info(fmt, ##msg);			\
				size = strlen(str);					\
      	    			log_to_file(str,size);			\
    			}\
		}while(0)  

	#ifdef  LOG_FILE
		#define debug_info(fmt,msg...)  log_file(INFO_LEVEL,fmt, ##msg)
		#define debug_warn(fmt,msg...) log_file(WARN_LEVEL,fmt, ##msg)
		#define debug_err(fmt,msg...)  \
					do{               \
						log_file(ERR_LEVEL,fmt, ##msg);    \
						BUG_ON();                    \
					}while(0)
	#else
		#define debug_info(fmt,msg...)  debug(INFO_LEVEL,fmt, ##msg)
		#define debug_warn(fmt,msg...) debug(WARN_LEVEL,fmt, ##msg)
		#define debug_err(fmt,msg...)  \
					do{               \
						debug(ERR_LEVEL,fmt, ##msg);    \
						 BUG_ON();                    \
					}while(0)
	#endif
	
#else
	#define debug(level, fmt, msg...)
	#define debug_info(fmt,msg...)
	#define debug_warn(fmt,msg...)
	#define debug_err(fmt, msg...)
#endif


#define dump_addr(addr) ({ \
	char addr_buf[100];                \
	do{                                 \
		char abuf[INET_ADDRSTRLEN];             \
		const char* info  = inet_ntop(AF_INET, &addr.sin_addr, abuf,INET_ADDRSTRLEN); \
     		sprintf(addr_buf,"ip[%s], port[%d]\n", info, ntohs(addr.sin_port));         \
	}while(0);                     \
	addr_buf;                     \
  })         



#endif  //__DEBUG__H__

